#include "json.h"
#include <assert.h>
#include <vector>
#include "JsonValue.h"

Json::Value::Value():m_jsonObject(NULL)
	,m_isRoot(false)
{

}

Json::Value::~Value()
{
	clear();
}

void Json::Value::clear()
{
	if( m_jsonObject != NULL && m_isRoot )
	{
		json_object_put(m_jsonObject);
		m_jsonObject = NULL;
	}

	for( ParamTable::iterator it = m_paramTable.begin(); it != m_paramTable.end() ; ++it )
	{
		if( it->second )
		{
			delete it->second;
		}
	}
	m_paramTable.clear();


	for( ValueArray::iterator it = m_valueArray.begin(); it != m_valueArray.end() ; ++it )
	{
		if( *it )
		{
			delete *it;
		}
	}
	m_valueArray.clear();
}

bool Json::Value::init( const char * jsonStr )
{
	bool ret = false;
	json_object * json = json_tokener_parse(jsonStr);
	if( json )
	{
		ret = init( json );
		m_isRoot = true;
	}
	return ret;
}

bool Json::Value::init( json_object * json )
{
	clear();

	if( !json )
		return false;
	
	m_isRoot = false;
	m_jsonObject = json;

	if( json_object_get_object(m_jsonObject) )
	{
		json_object_object_foreach( m_jsonObject, key, val )
		{
			Value * child = new Value();
			child->init( val );
			m_paramTable.insert(std::make_pair(key,child));
		}
	}
	else if( json_object_get_array(m_jsonObject) ) 
	{
		int size = json_object_array_length(m_jsonObject);
		for( int i = 0 ; i < size ; ++i )
		{ 
			Value * v = new Value();
			v->init( json_object_array_get_idx(m_jsonObject,i) );
			m_valueArray.push_back(v);
		}
	}

	return true;
}

bool	Json::Value::has( const std::string& key )
{
	return m_paramTable.find(key) != m_paramTable.end();
}


Json::Value& Json::Value::operator[]( const std::string& key )
{
	assert( m_paramTable.find(key) != m_paramTable.end() );
	return *m_paramTable[key];
}
const Json::Value& Json::Value::operator[]( const std::string& key ) const
{
	ParamTable::const_iterator it = m_paramTable.find(key);
	assert( it != m_paramTable.end() );
	return *it->second;
}


Json::Value& Json::Value::operator[]( int index )
{
	assert( type() == arrayValue );
	return *m_valueArray[index];
}



Json::ValueType Json::Value::type()
{
	if( m_jsonObject )
		return (ValueType)json_object_get_type(m_jsonObject);
	else
	{
		return Json::nullValue;
	}
}

Json::Value::iterator Json::Value::begin()
{
	return Json::Value::iterator(m_paramTable,m_paramTable.begin());
}

Json::Value::iterator Json::Value::end()
{
	return Json::Value::iterator(m_paramTable,m_paramTable.end());
}

int Json::Value::asInt()
{
	return json_object_get_int(m_jsonObject);
}

bool Json::Value::asBool()
{
	return json_object_get_boolean(m_jsonObject) != 0;
}

int Json::Value::size()
{
	int size = 0;
	assert( type() == arrayValue );
	if( json_object_get_array(m_jsonObject) )
	{
		size = json_object_array_length(m_jsonObject);
	}
	return size;
}

std::string Json::Value::asString()
{
	return std::string( json_object_get_string(m_jsonObject) );
}


//////////////////////////////////////////////////////////////////////////



Json::ValueIterator::ValueIterator( const ParamTable& table, ParamTable::iterator it ):m_paramTable(table),m_it(it)
{

}

Json::ValueIterator& Json::ValueIterator::operator++()
{
	++m_it;
	return *this;
}

Json::ValueIterator Json::ValueIterator::operator++( int )
{
	ValueIterator tmp = *this;
	m_it++;
	return tmp;
}

Json::ValueIterator& Json::ValueIterator::operator--()
{
	--m_it;
	return *this;
}

Json::ValueIterator Json::ValueIterator::operator--( int )
{
	ValueIterator tmp = *this;
	m_it++;
	return tmp;
}

bool Json::ValueIterator::operator==( const ValueIterator& v )
{
	return m_it == v.m_it;
}

bool Json::ValueIterator::operator!=( const ValueIterator& v )
{
	return m_it != v.m_it;
}

Json::Value& Json::ValueIterator::operator*()
{
	return *(m_it->second);
}
